/**
 * 标签模型
 * @description 定义视频标签的数据结构和相关方法
 */

const mongoose = require('mongoose');

// 标签ID计数器模式
const TagIdCounterSchema = new mongoose.Schema({
    _id: { type: String, default: 'tagId' },
    sequence_value: { type: Number, default: 0 }
});

const TagIdCounter = mongoose.model('TagIdCounter', TagIdCounterSchema);

// 标签模式
const TagSchema = new mongoose.Schema({
    tagId: {
        type: Number,
        unique: true,
        description: '标签的唯一标识符，自动递增生成'
    },
    name: {
        type: String,
        required: true,
        unique: true,
        trim: true,
        maxlength: 50,
        index: true,
        description: '标签名称，唯一且最大长度50字符，自动去除首尾空格'
    },
    description: {
        type: String,
        maxlength: 200,
        default: '',
        description: '标签的详细描述，最大长度200字符'
    },
    category: {
        type: String,
        enum: [
            'general',      // 通用标签
            'genre',        // 类型标签
            'mood',         // 情绪标签
            'topic',        // 主题标签
            'style',        // 风格标签
            'language',     // 语言标签
            'difficulty',   // 难度标签
            'duration',     // 时长标签
            'quality',      // 质量标签
            'custom'        // 自定义标签
        ],
        default: 'general',
        index: true,
        description: '标签分类，包括通用、类型、情绪、主题、风格、语言、难度、时长、质量、自定义等'
    },
    color: {
        type: String,
        default: '#007bff',
        match: /^#[0-9A-Fa-f]{6}$/,  // 验证十六进制颜色代码
        description: '标签显示颜色，使用十六进制颜色代码格式'
    },
    icon: {
        type: String,
        default: '',
        maxlength: 50,
        description: '标签图标，最大长度50字符'
    },
    usageCount: {
        type: Number,
        default: 0,
        min: 0,
        index: true,
        description: '标签使用次数，用于统计标签的热度'
    },
    isOfficial: {
        type: Boolean,
        default: false,
        index: true,
        description: '是否为官方标签，true表示官方标签，false表示用户创建的标签'
    },
    isActive: {
        type: Boolean,
        default: true,
        index: true,
        description: '标签是否激活，true表示可用，false表示已禁用'
    },
    isDeleted: {
        type: Boolean,
        default: false,
        index: true,
        description: '软删除标记，true表示已删除，false表示正常状态'
    },
    createdBy: {
        type: Number,
        default: null,
        index: true,
        description: '创建标签的用户ID，官方标签时为null'
    },
    createAt: {
        type: Date,
        default: Date.now,
        index: true,
        description: '标签的创建时间'
    },
    updateAt: {
        type: Date,
        default: Date.now,
        description: '标签的最后更新时间'
    }
});

// 复合索引
TagSchema.index({ name: 1, isDeleted: 1 });
TagSchema.index({ category: 1, isActive: 1, usageCount: -1 });
TagSchema.index({ isOfficial: 1, usageCount: -1 });
TagSchema.index({ createdBy: 1, createAt: -1 });

// 预保存钩子 - 自动生成标签ID和更新时间
TagSchema.pre('save', async function(next) {
    if (this.isNew) {
        try {
            const counter = await TagIdCounter.findByIdAndUpdate(
                'tagId',
                { $inc: { sequence_value: 1 } },
                { new: true, upsert: true }
            );
            this.tagId = counter.sequence_value;
        } catch (error) {
            return next(error);
        }
    }
    this.updateAt = new Date();
    next();
});

// 静态方法

/**
 * 创建标签
 * @param {Object} tagData - 标签数据
 * @returns {Promise<Object>} 创建的标签
 */
TagSchema.statics.createTag = async function(tagData) {
    const {
        name,
        description = '',
        category = 'general',
        color = '#007bff',
        icon = '',
        isOfficial = false,
        createdBy = null
    } = tagData;
    
    // 检查标签名是否已存在
    const existingTag = await this.findOne({ 
        name: name.trim().toLowerCase(), 
        isDeleted: false 
    });
    
    if (existingTag) {
        throw new Error('标签名已存在');
    }
    
    const tag = new this({
        name: name.trim(),
        description,
        category,
        color,
        icon,
        isOfficial,
        createdBy
    });
    
    await tag.save();
    return tag.getSafeJSON();
};

/**
 * 获取标签列表
 * @param {Object} options - 查询选项
 * @returns {Promise<Object>} 标签列表和分页信息
 */
TagSchema.statics.getTagList = async function(options) {
    const {
        category = null,
        isOfficial = null,
        isActive = true,
        keyword = '',
        sortBy = 'usageCount',
        sortOrder = 'desc',
        page = 1,
        limit = 20
    } = options;
    
    const skip = (page - 1) * limit;
    
    // 构建查询条件
    const query = {
        isDeleted: false
    };
    
    if (category) query.category = category;
    if (isOfficial !== null) query.isOfficial = isOfficial;
    if (isActive !== null) query.isActive = isActive;
    if (keyword) {
        query.$or = [
            { name: { $regex: keyword, $options: 'i' } },
            { description: { $regex: keyword, $options: 'i' } }
        ];
    }
    
    // 构建排序条件
    const sort = {};
    sort[sortBy] = sortOrder === 'desc' ? -1 : 1;
    
    const tags = await this.find(query)
        .sort(sort)
        .skip(skip)
        .limit(limit)
        .lean();
    
    const total = await this.countDocuments(query);
    
    return {
        tags: tags.map(tag => ({
            tagId: tag.tagId,
            name: tag.name,
            description: tag.description,
            category: tag.category,
            color: tag.color,
            icon: tag.icon,
            usageCount: tag.usageCount,
            isOfficial: tag.isOfficial,
            isActive: tag.isActive,
            createAt: tag.createAt
        })),
        pagination: {
            page,
            limit,
            total,
            pages: Math.ceil(total / limit)
        }
    };
};

/**
 * 获取标签详情
 * @param {number} tagId - 标签ID
 * @returns {Promise<Object|null>} 标签详情
 */
TagSchema.statics.getTagDetail = async function(tagId) {
    const tag = await this.findOne({ 
        tagId, 
        isDeleted: false 
    }).lean();
    
    if (!tag) return null;
    
    return {
        tagId: tag.tagId,
        name: tag.name,
        description: tag.description,
        category: tag.category,
        color: tag.color,
        icon: tag.icon,
        usageCount: tag.usageCount,
        isOfficial: tag.isOfficial,
        isActive: tag.isActive,
        createdBy: tag.createdBy,
        createAt: tag.createAt,
        updateAt: tag.updateAt
    };
};

/**
 * 更新标签
 * @param {number} tagId - 标签ID
 * @param {Object} updateData - 更新数据
 * @returns {Promise<Object|null>} 更新后的标签
 */
TagSchema.statics.updateTag = async function(tagId, updateData) {
    const {
        name,
        description,
        category,
        color,
        icon,
        isActive
    } = updateData;
    
    const tag = await this.findOne({ tagId, isDeleted: false });
    if (!tag) return null;
    
    // 如果更新名称，检查是否重复
    if (name && name.trim() !== tag.name) {
        const existingTag = await this.findOne({ 
            name: name.trim().toLowerCase(), 
            isDeleted: false,
            tagId: { $ne: tagId }
        });
        
        if (existingTag) {
            throw new Error('标签名已存在');
        }
        tag.name = name.trim();
    }
    
    if (description !== undefined) tag.description = description;
    if (category) tag.category = category;
    if (color) tag.color = color;
    if (icon !== undefined) tag.icon = icon;
    if (isActive !== undefined) tag.isActive = isActive;
    
    await tag.save();
    return tag.getSafeJSON();
};

/**
 * 删除标签
 * @param {number} tagId - 标签ID
 * @returns {Promise<boolean>} 删除是否成功
 */
TagSchema.statics.deleteTag = async function(tagId) {
    const result = await this.updateOne(
        { tagId, isDeleted: false },
        { 
            $set: { 
                isDeleted: true, 
                isActive: false,
                updateAt: new Date() 
            } 
        }
    );
    
    return result.modifiedCount > 0;
};

/**
 * 增加标签使用次数
 * @param {number} tagId - 标签ID
 * @param {number} count - 增加数量，默认为1
 * @returns {Promise<boolean>} 更新是否成功
 */
TagSchema.statics.increaseUsageCount = async function(tagId, count = 1) {
    const result = await this.updateOne(
        { tagId, isDeleted: false },
        { 
            $inc: { usageCount: count },
            $set: { updateAt: new Date() }
        }
    );
    
    return result.modifiedCount > 0;
};

/**
 * 减少标签使用次数
 * @param {number} tagId - 标签ID
 * @param {number} count - 减少数量，默认为1
 * @returns {Promise<boolean>} 更新是否成功
 */
TagSchema.statics.decreaseUsageCount = async function(tagId, count = 1) {
    const result = await this.updateOne(
        { tagId, isDeleted: false, usageCount: { $gte: count } },
        { 
            $inc: { usageCount: -count },
            $set: { updateAt: new Date() }
        }
    );
    
    return result.modifiedCount > 0;
};

/**
 * 批量获取标签信息
 * @param {Array} tagIds - 标签ID数组
 * @returns {Promise<Array>} 标签信息数组
 */
TagSchema.statics.getTagsByIds = async function(tagIds) {
    const tags = await this.find({ 
        tagId: { $in: tagIds }, 
        isDeleted: false 
    }).lean();
    
    return tags.map(tag => ({
        tagId: tag.tagId,
        name: tag.name,
        description: tag.description,
        category: tag.category,
        color: tag.color,
        icon: tag.icon,
        usageCount: tag.usageCount,
        isOfficial: tag.isOfficial
    }));
};

/**
 * 获取热门标签
 * @param {Object} options - 查询选项
 * @returns {Promise<Array>} 热门标签列表
 */
TagSchema.statics.getPopularTags = async function(options) {
    const {
        category = null,
        limit = 10,
        minUsageCount = 1
    } = options;
    
    const query = {
        isDeleted: false,
        isActive: true,
        usageCount: { $gte: minUsageCount }
    };
    
    if (category) query.category = category;
    
    const tags = await this.find(query)
        .sort({ usageCount: -1, createAt: -1 })
        .limit(limit)
        .lean();
    
    return tags.map(tag => ({
        tagId: tag.tagId,
        name: tag.name,
        category: tag.category,
        color: tag.color,
        icon: tag.icon,
        usageCount: tag.usageCount,
        isOfficial: tag.isOfficial
    }));
};

/**
 * 获取标签统计信息
 * @returns {Promise<Object>} 标签统计信息
 */
TagSchema.statics.getTagStats = async function() {
    const [totalCount, activeCount, categoryStats, officialCount] = await Promise.all([
        this.countDocuments({ isDeleted: false }),
        this.countDocuments({ isDeleted: false, isActive: true }),
        this.aggregate([
            {
                $match: { isDeleted: false, isActive: true }
            },
            {
                $group: {
                    _id: '$category',
                    count: { $sum: 1 },
                    totalUsage: { $sum: '$usageCount' }
                }
            }
        ]),
        this.countDocuments({ isDeleted: false, isOfficial: true })
    ]);
    
    const categoryStatsMap = {};
    categoryStats.forEach(stat => {
        categoryStatsMap[stat._id] = {
            count: stat.count,
            totalUsage: stat.totalUsage
        };
    });
    
    return {
        totalCount,
        activeCount,
        officialCount,
        categoryStats: categoryStatsMap
    };
};

/**
 * 搜索标签
 * @param {Object} options - 搜索选项
 * @returns {Promise<Array>} 搜索结果
 */
TagSchema.statics.searchTags = async function(options) {
    const {
        keyword,
        category = null,
        limit = 20,
        exactMatch = false
    } = options;
    
    if (!keyword) return [];
    
    const query = {
        isDeleted: false,
        isActive: true
    };
    
    if (category) query.category = category;
    
    if (exactMatch) {
        query.name = { $regex: `^${keyword}$`, $options: 'i' };
    } else {
        query.$or = [
            { name: { $regex: keyword, $options: 'i' } },
            { description: { $regex: keyword, $options: 'i' } }
        ];
    }
    
    const tags = await this.find(query)
        .sort({ usageCount: -1, name: 1 })
        .limit(limit)
        .lean();
    
    return tags.map(tag => ({
        tagId: tag.tagId,
        name: tag.name,
        category: tag.category,
        color: tag.color,
        icon: tag.icon,
        usageCount: tag.usageCount,
        isOfficial: tag.isOfficial
    }));
};

// 实例方法

/**
 * 获取安全的JSON数据
 * @returns {Object} 安全的标签数据
 */
TagSchema.methods.getSafeJSON = function() {
    return {
        tagId: this.tagId,
        name: this.name,
        description: this.description,
        category: this.category,
        color: this.color,
        icon: this.icon,
        usageCount: this.usageCount,
        isOfficial: this.isOfficial,
        isActive: this.isActive,
        createdBy: this.createdBy,
        createAt: this.createAt,
        updateAt: this.updateAt
    };
};

/**
 * 检查是否可以编辑
 * @param {number} userId - 用户ID
 * @returns {boolean} 是否可以编辑
 */
TagSchema.methods.canEdit = function(userId) {
    // 官方标签只能由管理员编辑
    if (this.isOfficial) return false;
    
    // 创建者可以编辑自己的标签
    return this.createdBy === userId;
};

/**
 * 检查是否可以删除
 * @param {number} userId - 用户ID
 * @returns {boolean} 是否可以删除
 */
TagSchema.methods.canDelete = function(userId) {
    // 官方标签不能删除
    if (this.isOfficial) return false;
    
    // 使用次数大于0的标签不能删除
    if (this.usageCount > 0) return false;
    
    // 创建者可以删除自己的标签
    return this.createdBy === userId;
};

/**
 * 激活标签
 * @returns {Promise<Object>} 更新后的标签
 */
TagSchema.methods.activate = async function() {
    this.isActive = true;
    this.updateAt = new Date();
    await this.save();
    return this.getSafeJSON();
};

/**
 * 停用标签
 * @returns {Promise<Object>} 更新后的标签
 */
TagSchema.methods.deactivate = async function() {
    this.isActive = false;
    this.updateAt = new Date();
    await this.save();
    return this.getSafeJSON();
};

const Tags = mongoose.model('Tags', TagSchema);

module.exports = Tags;